home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / pvmshmem.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  20KB  |  868 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: pvmshmem.c,v 1.7 1997/07/08 20:18:07 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *  pvmshmem.c
  35.  *
  36.  *  Shared-memory stuff.
  37.  *
  38. $Log: pvmshmem.c,v $
  39.  * Revision 1.7  1997/07/08  20:18:07  pvmsrc
  40.  * Better logging in peer_conn()
  41.  *
  42.  * Revision 1.6  1997/06/25  22:11:10  pvmsrc
  43.  * Markus adds his frigging name to the author list of
  44.  *     every file he ever looked at...
  45.  *
  46.  * Revision 1.5  1997/05/21  16:01:55  pvmsrc
  47.  * Updated ifdefs to include AIX4MP arch type.
  48.  *
  49.  * Revision 1.4  1997/04/25  19:18:14  pvmsrc
  50.  * Corrected includes.
  51.  *
  52.  * Revision 1.3  1997/01/28  19:27:30  pvmsrc
  53.  * New Copyright Notice & Authors.
  54.  *
  55.  * Revision 1.2  1996/10/25  14:19:06  pvmsrc
  56.  * Replaced old #includes for protocol headers:
  57.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  58.  * With #include of new combined header:
  59.  *     - <pvmproto.h>
  60.  *
  61.  * Revision 1.1  1996/09/23  23:44:40  pvmsrc
  62.  * Initial revision
  63.  *
  64.  * Revision 1.21  1995/11/02  16:33:04  manchek
  65.  * peer_conn returns -1 if peer has disconnected
  66.  *
  67.  * Revision 1.21  1995/11/02  16:33:04  manchek
  68.  * peer_conn returns -1 if peer has disconnected
  69.  *
  70.  * Revision 1.20  1995/09/07  17:38:27  manchek
  71.  * Add __synch() when releasing lock.
  72.  *
  73.  * Revision 1.19  1995/07/28  15:42:45  manchek
  74.  * _touch does all pages, uses PVMTOUCH envar to switch on
  75.  *
  76.  * Revision 1.18  1995/07/28  14:31:42  manchek
  77.  * oops, shm_search had too many args
  78.  *
  79.  * Revision 1.17  1995/07/24  18:32:21  manchek
  80.  * da_new warns of using malloc.
  81.  * had the wrong ST_ state test in peer_conn
  82.  *
  83.  * Revision 1.16  1995/07/19  18:05:14  manchek
  84.  * peer_dump prints peer info even if stat fails
  85.  *
  86.  * Revision 1.15  1995/07/12  01:32:52  manchek
  87.  * peer_conn checks that p_buf is nonzero before returning connection,
  88.  * also that tid and state in pidtid table are correct.
  89.  * peer_detach zeros p_buf before detaching in case interrupt occurs,
  90.  * now unlinks and frees peer struct.
  91.  * peer_cleanup adjusted to this
  92.  *
  93.  * Revision 1.14  1995/07/05  15:33:32  manchek
  94.  * clean up semaphore too in peer_detach
  95.  *
  96.  * Revision 1.13  1995/07/03  21:15:40  manchek
  97.  * declare getenv
  98.  *
  99.  * Revision 1.12  1995/07/03  20:36:14  manchek
  100.  * made convex loopback code the general case in peer_conn()
  101.  *
  102.  * Revision 1.11  1995/07/03  19:35:43  manchek
  103.  * hellish cleanup of comments and formatting.
  104.  * removed POWER4 ifdefs.
  105.  * maintain shared page counter to da_xxx to help detect deadlock.
  106.  * shared segment key now created by task, passed through pt_key.
  107.  * added pvmshmkey(), nextpvmshmkey()
  108.  *
  109.  * Revision 1.10  1995/06/28  16:08:49  manchek
  110.  * peer_conn returns new connection status
  111.  *
  112.  * Revision 1.9  1995/06/02  16:22:10  manchek
  113.  * zero p_buf in peer_detach() so we don't reference segment later
  114.  *
  115.  * Revision 1.8  1995/05/30  14:37:38  manchek
  116.  * touched shared segment after detaching in peer_detach()
  117.  *
  118.  * Revision 1.7  1995/05/24  19:08:55  manchek
  119.  * changed HPPA shared memory name to HPPAMP
  120.  *
  121.  * Revision 1.6  1995/05/22  19:53:00  manchek
  122.  * added ifdefs for RS6KMP
  123.  *
  124.  * Revision 1.5  1995/05/18  17:22:34  manchek
  125.  * need to import pvminbox and myshmbufid
  126.  *
  127.  * Revision 1.4  1995/05/17  16:47:22  manchek
  128.  * bug fixes from SGI and Convex.
  129.  * added CSPP shared memory support
  130.  *
  131.  * Revision 1.3  1994/11/08  15:36:49  manchek
  132.  * shared memory damage control
  133.  *
  134.  * Revision 1.2  1994/06/04  21:44:25  manchek
  135.  * updated header
  136.  *
  137.  * Revision 1.1  1994/06/03  20:38:26  manchek
  138.  * Initial revision
  139.  *
  140.  */
  141.  
  142. #include <sys/param.h>
  143. #include <fcntl.h>
  144. #include <string.h>
  145. #include <sys/ipc.h>
  146. #include <sys/shm.h>
  147. #include <sys/sem.h>
  148. #ifdef IMA_SYMM
  149. #include <parallel/parallel.h>
  150. #endif
  151. #include <errno.h>
  152.  
  153. #include <pvm3.h>
  154. #include <pvmproto.h>
  155. #include "pvmalloc.h"
  156. #include "listmac.h"
  157. #include "pvmshmem.h"
  158. #include "bfunc.h"
  159.  
  160. #include "global.h"
  161.  
  162. #ifndef min
  163. #define min(a,b)    ((a)<(b)?(a):(b))
  164. #endif
  165.  
  166. extern int pvmdebmask;                /* from pvmd.c or lpvmshmem.c */
  167. extern int pvmmytid;                /* from pvmd.c or lpvmshmem.c */
  168. extern int pvmpgsz;                    /* from pvmdshmem.c or lpvmshmem.c */
  169. extern int pgsz;                    /* from pvmdshmem.c or lpvmshmem.c */
  170. extern char *outmsgbuf;                /* from pvmdshmem.c or lpvmshmem.c */
  171. extern int outbufsz;                /* from pvmdshmem.c or lpvmshmem.c */
  172. extern int nbufsowned;                /* from pvmdshmem.c or lpvmshmem.c */
  173. extern char *infopage;                /* from pvmdshmem.c or lpvmshmem.c */
  174. extern struct pidtid *pidtids;        /* from pvmdshmem.c or lpvmshmem.c */
  175. extern int maxpidtid;                /* from pvmdshmem.c or lpvmshmem.c */
  176. extern int shmbufsiz;                /* from pvmdshmem.c or lpvmshmem.c */
  177. extern int myshmbufid;                /* from pvmdshmem.c or lpvmshmem.c */
  178. extern char *pvminbox;                /* from pvmdshmem.c or lpvmshmem.c */
  179.  
  180. char *getenv();
  181.  
  182. /***************
  183.  **  Globals  **
  184.  **           **
  185.  ***************/
  186.  
  187. struct peer *peers = 0;                /* tasks we're connected to */
  188. int bufpageused = 0;                /* number of dirty pages in msg buf */
  189.  
  190.  
  191. /***************
  192.  **  Private  **
  193.  **           **
  194.  ***************/
  195.  
  196. static char pvmtxt[512];            /* scratch for error log */
  197. static int nxtpage = 0;                /* next free page in outgoing msg buf */
  198.  
  199.  
  200. /*******************************************************
  201.  **  Shared-memory data buffer manipulation routines  **
  202.  **                                                   **
  203.  *******************************************************/
  204.  
  205. /*    msgbufinit()
  206. *
  207. *    Initialize the shared-memory message buffer.
  208. */
  209.  
  210. int
  211. msgbufinit(buf)
  212.     char *buf;
  213. {
  214.     char *p, *end;
  215.  
  216.     end = buf + shmbufsiz;
  217. #ifndef IMA_KSR1
  218. #ifdef IMA_SUNMP
  219.     cond_init(&((struct msgboxhdr *)buf)->mb_cond, USYNC_PROCESS, 0);
  220. #endif
  221. #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP)
  222.     pthread_cond_init(&((struct msgboxhdr *)buf)->mb_cond, NULL);
  223. #endif
  224.     PAGEINITLOCK(&((struct msgboxhdr *)buf)->mb_lock);
  225.     ((struct msgboxhdr *)buf)->mb_sleep = 0;
  226. #endif
  227.     ((struct msgboxhdr *)buf)->mb_read = -1;
  228.     ((struct msgboxhdr *)buf)->mb_last = -1;
  229.  
  230.     for (p = outmsgbuf; p < end; p += pvmpgsz) {
  231. #if !defined(TEST_ADD) && !defined(IMA_KSR1)
  232.         PAGEINITLOCK(&((struct shmpghdr *)p)->pg_lock);
  233. #endif
  234.         ((struct shmpghdr *)p)->pg_priv = 0;
  235.         ((struct shmpghdr *)p)->pg_ref = 0;
  236.     }
  237.  
  238.     if (pvmdebmask & PDMNODE) {
  239.         sprintf(pvmtxt, "msgbufinit() outmsgbuf=0x%x\n", outmsgbuf);
  240.         pvmlogerror(pvmtxt);
  241.         sprintf(pvmtxt, "msgbufinit() last buffer=0x%x\n", p - pvmpgsz);
  242.         pvmlogerror(pvmtxt);
  243.         sprintf(pvmtxt, "msgbufinit() pvmpgsz=%d\n", pvmpgsz);
  244.         pvmlogerror(pvmtxt);
  245.     }
  246.     return 0;
  247. }
  248.  
  249.  
  250. /*    da_new()
  251. *
  252. *    Replacement for functions in pvmdabuf.c
  253. *
  254. *    Try to find a free page. Check page 0 first, and then the current one.
  255. *    If neither is free, then move beyond the current page towards the end
  256. *    of the buffer.
  257. */
  258.  
  259. char *
  260. da_new(len)
  261.     int len;
  262. {
  263.     char *p;
  264.     int start;
  265.  
  266.     if (len > pvmpgsz - PVMPAGEHDR) {
  267.         sprintf(pvmtxt, "da_new() len = %d: frag must fit in a page\n", len);
  268.         pvmlogerror(pvmtxt);
  269.         return 0;
  270.     }
  271.  
  272. #ifdef IMA_CSPP
  273.     p = outmsgbuf + nxtpage*pvmpgsz;
  274. #else
  275.     p = outmsgbuf;
  276.     if (nxtpage && !((struct shmpghdr *)p)->pg_ref)
  277.         nxtpage = 0;        /* recycle to avoid page fault */
  278.     else
  279.         p += nxtpage*pvmpgsz;
  280. #endif
  281.  
  282.     start = nxtpage;
  283.     while (1) {
  284.         if (((struct shmpghdr *)p)->pg_ref == 0) {
  285.             nbufsowned++;
  286.             break;
  287.         }
  288.         if (++nxtpage == outbufsz) {
  289.             nxtpage = 0;
  290.             p = outmsgbuf;
  291.  
  292.         } else
  293.             p += pvmpgsz;
  294.  
  295.         if (nxtpage == start) {        /* buffer full */
  296.             p = TALLOC(len + PVMPAGEHDR, char, "data");
  297.             if (p) {
  298.                 static int once = 1;
  299.  
  300.                 if (once) {
  301.                     once = 0;
  302.                     pvmlogerror("da_new() Warning: shared buffer full, using malloc\n");
  303.                 }
  304. #if !defined(IMA_KSR1) && !defined(TEST_ADD)
  305.                 PAGEINITLOCK(&((struct shmpghdr *)p)->pg_lock);
  306. #endif
  307.                 ((struct shmpghdr *)p)->pg_priv = 1;
  308.             }
  309.             break;
  310.         }
  311.     }
  312.  
  313.     if (nxtpage >= bufpageused)
  314.         bufpageused = nxtpage + 1;
  315.     if (p) {
  316.         ((struct shmpghdr *)p)->pg_ref = 1;
  317.         return (p + PVMPAGEHDR);
  318.     } else
  319.         return 0;
  320. }
  321.  
  322. void
  323. da_ref(p)
  324.     char *p;
  325. {
  326.     p -= PVMPAGEHDR;
  327. #ifdef TEST_ADD
  328.     TEST_ADD(&((struct shmpghdr *)p)->pg_ref, 1);
  329. #else
  330.     PAGELOCK(&((struct shmpghdr *)p)->pg_lock);
  331.     ++((struct shmpghdr *)p)->pg_ref;
  332.     PAGEUNLOCK(&((struct shmpghdr *)p)->pg_lock);
  333. #endif
  334. }
  335.  
  336.  
  337. void
  338. da_unref(p)
  339.     char *p;
  340. {
  341.     p -= PVMPAGEHDR;
  342. #ifdef TEST_ADD
  343.     if ((long) TEST_ADD(&((struct shmpghdr *)p)->pg_ref, -1L) < 0)
  344.         pvmlogerror("ref count is negative!\n");
  345. #else
  346.     PAGELOCK(&((struct shmpghdr *)p)->pg_lock);
  347.     if (--((struct shmpghdr *)p)->pg_ref < 0) {
  348.         sprintf(pvmtxt, "ref = %d on page %d\n",
  349.             ((struct shmpghdr *)p)->pg_ref, (p - outmsgbuf)/pgsz + 1);
  350.         pvmlogerror(pvmtxt);
  351.     }
  352.     PAGEUNLOCK(&((struct shmpghdr *)p)->pg_lock);
  353. #endif
  354.     if (((struct shmpghdr *)p)->pg_priv) {
  355.         if (((struct shmpghdr *)p)->pg_ref < 1)
  356.             PVM_FREE(p);
  357.     } else {
  358.         if (p >= outmsgbuf && p < outmsgbuf + outbufsz * pvmpgsz)
  359.             nbufsowned--;
  360.     }
  361. }
  362.  
  363.  
  364. void
  365. peer_init()
  366. {
  367.     peers = TALLOC(1, struct peer, "peer");
  368.     BZERO((char*)peers, sizeof(struct peer));
  369.     peers->p_link = peers->p_rlink = peers;
  370. }
  371.  
  372.  
  373. /*    peer_conn()
  374. *
  375. *    Attach peer's message buffer.
  376. *    Returns pointer to peer struct,
  377. *    Else 0 if peer isn't ready to receive yet
  378. *    Or  -1 if peer can't be contacted via shared memory or has disconnected.
  379. */
  380.  
  381. struct peer *
  382. peer_conn(tid, new_connection)
  383.     int tid;
  384.     int *new_connection;
  385. {
  386.     struct peer *pp;
  387.     char *p;
  388.  
  389.     if (new_connection)
  390.         *new_connection = 0;
  391.     for (pp = peers->p_link; pp != peers; pp = pp->p_link) {
  392.         if (pp->p_tid == tid) {        /* already connected */
  393.             if (pp->p_exited || !pp->p_buf) {
  394.                 if (pvmdebmask & PDMMEM) {
  395.                     sprintf(pvmtxt, "peer_conn() t%x has exited?\n", tid);
  396.                      pvmlogerror(pvmtxt);
  397.                  }
  398.                 return ((struct peer *)-1L);
  399.                 }
  400.             else {
  401.                 if (pvmdebmask & PDMMEM) {
  402.                     sprintf(pvmtxt, "peer_conn() to t%x got pp addr %lx\n", 
  403.                             tid, pp);
  404.                      pvmlogerror(pvmtxt);
  405.                  }
  406.                 return pp;
  407.  
  408.                 }
  409.         }
  410.     /*
  411.     * test p_buf in case we're in the process of destroying this peer struct
  412.     */
  413.  
  414. #if 0
  415.     /* XXX disconnect from inactive peers */
  416.         if (pp2->p_tid == -1) {        /* used by pvmd */
  417.             /* peer_detach(pp2); */
  418.             shmdt(pp2->p_buf);
  419.             LISTDELETE(pp2, p_link, p_rlink);
  420.             PVM_FREE(pp2);
  421.         }
  422. #endif
  423.     }
  424.  
  425.     if (pp == peers && tid == pvmmytid) {
  426.         if (!(pp = TALLOC(1, struct peer, "peer"))) {
  427.             pvmlogerror("peer_conn() can't get memory\n");
  428.             return (struct peer *)0;
  429.         }
  430.         BZERO((char*)pp, sizeof(struct peer));
  431.         pp->p_buf = pvminbox;
  432.         pp->p_shmid = myshmbufid;
  433.         pp->p_tid = pvmmytid;
  434.         pp->p_semid = -1;
  435.         LISTPUTAFTER(peers, pp, p_link, p_rlink);
  436.  
  437.     } else if (pp == peers && tid) {
  438.         int bufid, ntids, i, key;
  439.  
  440.         /* PAGELOCK(pvminfo); */
  441.     /* XXX the first few don't have to search the whole empty table. hmm. */
  442.         ntids = min(maxpidtid, ((struct shmpghdr *)infopage)->pg_ref);
  443.         for (i = 0; i < ntids; i++)
  444.             if (pidtids[i].pt_tid == tid && pidtids[i].pt_stat != ST_EXIT) {
  445.                 if (pidtids[i].pt_stat == ST_NOTREADY)
  446.                     return (struct peer *)0;
  447.                 if (pidtids[i].pt_stat == ST_SOCKET)
  448.                     return (struct peer *)-1L;
  449.                 /* must be ST_SHMEM or ST_FINISH */
  450.                 break;
  451.             }
  452.         if (i == ntids) 
  453.             {
  454.             if (pvmdebmask & PDMMEM) {
  455.                 sprintf(pvmtxt, "peer_conn() could not find t%x in daemon list\n", tid);
  456.              pvmlogerror(pvmtxt);
  457.              }
  458.             return (struct peer *)-1L;
  459.         /* PAGEUNLOCK(pvminfo); */
  460.         }
  461.  
  462.         key = pidtids[i].pt_key;
  463.         if ((bufid = shmget((key_t)key, shmbufsiz, 0)) == -1) {
  464.             sprintf(pvmtxt, "peer_conn() shmget t%x key 0x%x", tid, key);
  465.             pvmlogperror(pvmtxt);
  466.             return (struct peer *)0;
  467.         }
  468.         while ((p = (char *)shmat(bufid, 0, 0)) == (char *)-1L) {
  469.             sprintf(pvmtxt, "peer_conn() shmat to t%x using bufid %d\n", 
  470.                     tid, bufid);
  471.             pvmlogperror(pvmtxt);
  472.             if (errno == EMFILE && (pp = peers->p_rlink) != peers) {
  473.                 shmdt(pp->p_buf);
  474.                 LISTDELETE(pp, p_link, p_rlink);
  475.                 PVM_FREE(pp);
  476.                 continue;
  477.             }
  478.             return (struct peer *)0;
  479.         }
  480.  
  481. #ifdef IMA_CSPP
  482.         _touch(p);
  483. #endif
  484.  
  485.         if (!(pp = TALLOC(1, struct peer, "peer"))) {
  486.             pvmlogerror("peer_conn() can't get memory\n");
  487.             return (struct peer *)0;
  488.         }
  489.         BZERO((char*)pp, sizeof(struct peer));
  490.         pp->p_key = key;
  491.         pp->p_tid = tid;
  492.         pp->p_buf = p;
  493.         pp->p_shmid = bufid;
  494.         pp->p_semid = -1;
  495. #ifdef IMA_CSPP
  496.         pp->p_node = pidtids[i].pt_node;
  497. #endif
  498.         pp->p_exited = 0;
  499.         LISTPUTAFTER(peers, pp, p_link, p_rlink);
  500.         if (new_connection)
  501.             *new_connection = 1;
  502.     }
  503.  
  504.     return pp;
  505. }
  506.  
  507.  
  508. /*    peer_wake()
  509. *
  510. *    Wake up sleeping task that we just sent message to.
  511. */
  512.  
  513. void
  514. peer_wake(pp)
  515.     struct peer *pp;
  516. {
  517.     struct sembuf    sops;
  518.  
  519.     if (pp->p_semid == -1
  520.     && (pp->p_semid = semget((key_t)pp->p_key, 1, PERMS)) == -1) {
  521.         sprintf(pvmtxt, "peer_wake() semget t%x key 0x%x\n",
  522.                 pp->p_tid, pp->p_key);
  523.         pvmlogperror(pvmtxt);
  524.         return;
  525.     }
  526.     sops.sem_num = 0;
  527.     sops.sem_op = 1;
  528.     sops.sem_flg = 0;
  529.     if (semop(pp->p_semid, &sops, 1) == -1) {
  530.         sprintf(pvmtxt, "peer_wake() semop t%x\n", pp->p_tid);
  531.         pvmlogperror(pvmtxt);
  532.  
  533.     } else if (pvmdebmask & PDMSEM) {
  534.         sprintf(pvmtxt,"peer_wake() sem %d\n", pp->p_semid);
  535.         pvmlogerror(pvmtxt);
  536.     }
  537. }
  538.  
  539.  
  540. /*    peer_detach()
  541. *
  542. *    Detach peer's msg buffer, destroy if no one else is attached to it.
  543. */
  544.  
  545. int
  546. peer_detach(pp)
  547.     struct peer *pp;
  548. {
  549.     struct shmid_ds shmds;
  550.     char *p;
  551.  
  552.     if (pp->p_tid != pvmmytid) {
  553.     /*
  554.     * zero p_buf before destroying it in case we're interrupted right here.
  555.     * yes, it happend.
  556.     */
  557.         if (p = pp->p_buf) {
  558.             pp->p_buf = 0;
  559.             if (shmdt(p) == -1)
  560.                 pvmlogperror("peer_detach() shmdt");
  561.         }
  562.  
  563.         if (!shmctl(pp->p_shmid, IPC_STAT, &shmds) && shmds.shm_nattch == 0) {
  564.             shmctl(pp->p_shmid, IPC_RMID, (struct shmid_ds *)0);
  565.  
  566. #ifdef    USERECVSEMAPHORE
  567.             if (pp->p_semid == -1 && pp->p_key)
  568.                 pp->p_semid = semget((key_t)pp->p_key, 1, PERMS);
  569.             if (pp->p_semid != -1)
  570.                 semctl(pp->p_semid, 0, IPC_RMID);
  571. #endif
  572.         }
  573.     }
  574.  
  575.     LISTDELETE(pp, p_link, p_rlink);
  576.     PVM_FREE(pp);
  577.     return 0;
  578. }
  579.  
  580.  
  581. void
  582. peer_cleanup()
  583. {
  584.     while (peers->p_link != peers)
  585.         peer_detach(peers->p_link);
  586. }
  587.  
  588.  
  589. int
  590. peer_dump()
  591. {
  592.     struct peer *pp;
  593.     struct shmid_ds shmds;
  594.  
  595.     pvmlogerror("peer_dump()\n");
  596.     for (pp = peers->p_link; pp != peers; pp = pp->p_link) {
  597.         if (shmctl(pp->p_shmid, IPC_STAT, &shmds) == -1) {
  598.             sprintf(pvmtxt, "peer_dump() shmctl STAT %d", pp->p_shmid);
  599.             pvmlogperror(pvmtxt);
  600.             sprintf(pvmtxt,
  601.                     " t%x key=0x%x shmid=%d semid=%d shmlen=%d\n",
  602.                     pp->p_tid, pp->p_key, pp->p_shmid, pp->p_semid, pp->p_dlen);
  603.             pvmlogerror(pvmtxt);
  604.  
  605.         } else {
  606.             sprintf(pvmtxt,
  607.                     " t%x key=0x%x shmid=%d semid=%d shmlen=%d shmna=%d\n",
  608.                     pp->p_tid, pp->p_key, pp->p_shmid, pp->p_semid, pp->p_dlen,
  609.                     (int)shmds.shm_nattch);
  610.             pvmlogerror(pvmtxt);
  611.         }
  612.     }
  613.     return 0;
  614. }
  615.  
  616.  
  617. #ifdef IMA_CSPP
  618. #define    SHMIDPIDPART    0xfff
  619. #endif
  620.  
  621. #ifndef    SHMIDUIDPART
  622. #define    SHMIDUIDPART    0xffff0000
  623. #endif
  624. #ifndef    SHMIDPIDPART
  625. #define    SHMIDPIDPART    0xffff
  626. #endif
  627.  
  628. /*    pvmshmkey()
  629. *
  630. *    Get the shared-memory segment key of the pvmd, if pid == 0,
  631. *    else of process pid.
  632. */
  633.  
  634. int
  635. pvmshmkey(pid)
  636.     int pid;
  637. {
  638.     static int pvmd_key = 0;
  639.  
  640.     int k;
  641.     char *p;
  642.  
  643.     if (!pvmd_key) {
  644.         if (p = getenv("PVMKEY"))
  645.             pvmd_key = atoi(p);
  646.         else
  647.             pvmd_key = getuid();
  648.         pvmd_key = (pvmd_key << 16) & SHMIDUIDPART;
  649.         if (!pvmd_key)
  650.             pvmd_key = SHMIDUIDPART;
  651. #ifdef IMA_CSPP
  652.         pvmd_key |= (get_scid() & 0xf) << 12;
  653. #endif
  654.     }
  655.  
  656.     if (pid) {
  657.         if (!(pid &= SHMIDPIDPART))
  658.             pid = 1;
  659.         k = pvmd_key | pid;
  660.         if (pvmdebmask & (PDMMEM | PDMSEM)) {
  661.             sprintf(pvmtxt, "pvmshmkey(): shm/sem key is 0x%x\n", k);
  662.             pvmlogerror(pvmtxt);
  663.         }
  664.  
  665.     } else {
  666.         k = pvmd_key;
  667.  
  668.         if (pvmdebmask & (PDMMEM | PDMSEM)) {
  669.             sprintf(pvmtxt, "pvmshmkey(): pvmd shm/sem key is 0x%x\n", k);
  670.             pvmlogerror(pvmtxt);
  671.         }
  672.     }
  673.  
  674.     return k;
  675. }
  676.  
  677.  
  678. /*    nextpvmshmkey()
  679. *
  680. *    Get a new shared memory key to try (in case the default failed).
  681. */
  682.  
  683. int
  684. nextpvmshmkey(key)
  685.     int key;
  686. {
  687.     int pid;
  688.  
  689.     pid = (key + 1) & SHMIDPIDPART;
  690.     if (!pid)
  691.         pid = 1;
  692.     pid |= pvmshmkey(0);
  693.     if (pvmdebmask & (PDMMEM | PDMSEM)) {
  694.         sprintf(pvmtxt, "nextpvmshmkey() shm/sem key is 0x%x\n", pid);
  695.         pvmlogerror(pvmtxt);
  696.     }
  697.     return pid;
  698. }
  699.  
  700.  
  701. #if defined(IMA_CSPP) || defined(IMA_HPPAMP)
  702.  
  703. void
  704. init_lock(vp, f, l)
  705.     pvmspplock_t *vp;
  706.     char *f;
  707.     int l;
  708. {
  709.     if (pvmdebmask & PDMLOCK) {
  710.         sprintf(pvmtxt,"init_lock(): init %#x from %s line %d\n", vp,f,l);
  711.         pvmlogerror(pvmtxt);
  712.     }
  713.  
  714.     *(int *)vp = 1;
  715. }
  716.  
  717. int
  718. acquire_lock(vp, f, l)
  719.     pvmspplock_t *vp;
  720.     char *f;
  721.     int l;
  722. {
  723.     int * volatile ip = (int *)vp;
  724.     int i=0, j=0;
  725.  
  726.     if (pvmdebmask & PDMLOCK) {
  727.         sprintf(pvmtxt,"acquire_lock(): polling %#x from %s line %d\n", ip,f,l);
  728.         pvmlogerror(pvmtxt);
  729.     }
  730.  
  731.     while (1) {
  732.         while (!(*ip)) i++;
  733.         if (__ldcws32(ip))
  734.             break;
  735.         j++;
  736.     }
  737.  
  738.     if (pvmdebmask & PDMLOCK) {
  739.         if (i)
  740.             sprintf(pvmtxt,"acquire_lock(): acquired %#x after %d/%d polls\n",
  741.                 ip, i, j);
  742.         else
  743.             sprintf(pvmtxt,"acquire_lock(): acquired %#x\n", ip);
  744.         pvmlogerror(pvmtxt);
  745.     }
  746.     return 0;
  747. }
  748.  
  749. int
  750. release_lock(vp,f,l)
  751.     pvmspplock_t *vp;
  752.     char *f;
  753.     int l;
  754. {
  755.     if (pvmdebmask & PDMLOCK) {
  756.         sprintf(pvmtxt,"release_lock(): releasing %#x from %s line %d\n", vp,f,l);
  757.         pvmlogerror(pvmtxt);
  758.     }
  759.     __synch();
  760.     *(int *)vp = 1;
  761.     return 0;
  762. }
  763.  
  764. #endif    /*defined(IMA_CSPP) || defined(IMA_HPPAMP)*/
  765.  
  766. #ifdef IMA_CSPP
  767. static int touch_flg = -1;        /* flag to page memory early */
  768. #define DONT_TOUCH   0
  769. #define TOUCH_PAGES  1
  770.  
  771. /* _touch()
  772.  *
  773.  *  Touch all the pages in this shared memory block
  774.  */
  775.  
  776. static void
  777. _touch(addr)
  778. char *addr;
  779. {
  780.     switch (touch_flg) {
  781.     case TOUCH_PAGES:
  782.         {
  783.             char *shm_pg;
  784.             int pgsz = sysconf(_SC_PAGESIZE);
  785.  
  786.             if(pvmdebmask & PDMMEM) {
  787.                 sprintf(pvmtxt, "Touching block at addr 0x%x (%d bytes)\n",
  788.                     addr, shmbufsiz);
  789.                 pvmlogerror(pvmtxt);
  790.             }
  791.  
  792.             for (shm_pg = addr; shm_pg < (addr + shmbufsiz); shm_pg += pgsz)
  793.                 shm_pg[63] = 0;
  794.         }
  795.         break;
  796.  
  797.     case DONT_TOUCH:
  798.         break;
  799.  
  800.     default:
  801.         touch_flg = (getenv("PVMTOUCH") ? TOUCH_PAGES : DONT_TOUCH);
  802.         if(pvmdebmask & (PDMTASK|PDMMEM)) {
  803.             sprintf(pvmtxt, "Shared memory touching: %s\n",
  804.                 touch_flg ? "ON" : "OFF" );
  805.             pvmlogerror(pvmtxt);
  806.         }
  807.     }
  808.     return;
  809. }
  810.  
  811. /*
  812.  * ---> On CSPP SYS V memory systems, the VM addr given to the PVM daemon may
  813.  * ---> not work for the PVM clients.  Search for an open spot in the VM space
  814.  * ---> that will work for SOM and ESOM executables.
  815.  */
  816.  
  817. #define GATEWY_LO_ADDR  0xbff00000
  818. #define GATEWY_HI_ADDR  0xc0010000
  819. #define SHM_HI_ADDR     0xf0000000
  820. #define SHM_LO_ADDR     0x80000000
  821.  
  822. char *
  823. shm_search(bufid)
  824. int bufid;
  825. {
  826.     unsigned int i, unmapped = 1;
  827.     char *inbox;
  828.     int shm_incr_addr = (shmbufsiz + 4095) & (~4095);    /* round up */
  829.  
  830.     for(i = GATEWY_LO_ADDR; i > SHM_LO_ADDR && unmapped; i-=shm_incr_addr) {
  831.         inbox = (char*)shmat(bufid, (char*) i, 0);
  832.         unmapped = (inbox == (char*)-1L);
  833.         if ( unmapped && (pvmdebmask & PDMMEM) ) {
  834.             sprintf(pvmtxt, "shm_search(): shmat() failed attach at %#x\n", i);
  835.             pvmlogerror(pvmtxt);
  836.         }
  837.     }
  838.  
  839.     for(i = GATEWY_HI_ADDR; i < SHM_HI_ADDR && unmapped; i+=shm_incr_addr) {
  840.         inbox = (char*)shmat(bufid, (char*) i, 0);
  841.         unmapped = (inbox == (char*)-1L);
  842.         if ( unmapped && (pvmdebmask & PDMMEM) ) {
  843.             sprintf(pvmtxt, "shm_search(): shmat() failed attach at %#x\n", i);
  844.             pvmlogerror(pvmtxt);
  845.         }
  846.     }
  847.  
  848.     if ( unmapped ) {
  849.         pvmlogerror("shm_search(): Unable to shmat\n");
  850.         return (char *) -1;
  851.     }
  852.  
  853.     if (pvmdebmask & PDMMEM) {
  854.         sprintf(pvmtxt, "shm_search(): shmat attached to addr %x\n",
  855.             (unsigned int) inbox);
  856.         pvmlogerror(pvmtxt);
  857.     }
  858.  
  859.     /* Page in the shared memory */
  860.  
  861.     _touch(inbox);
  862.  
  863.     return inbox;
  864. }
  865. #endif    /*IMA_CSPP*/
  866.  
  867.  
  868.